#pragma once
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <vector>

class AudioBuffer {
 public:
  AudioBuffer(size_t capacity) : buffer(capacity), read_pos(0), write_pos(0) {}

  // 线程安全的写入方法（阻塞式）
  void write(const float* data, size_t samples) {
    std::unique_lock<std::mutex> lock(mutex);

    size_t remaining = samples;
    while (remaining > 0) {
      // 等待可用空间
      space_available.wait(
          lock, [this, remaining] { return available_space() >= remaining; });
      // 计算连续可写空间
      const size_t contiguous = std::min(remaining, contiguous_space());

      // 写入数据
      for (size_t i = 0; i < contiguous; ++i) {
        buffer[write_pos] = data[i];
        write_pos = (write_pos + 1) % buffer.size();
      }

      data += contiguous;
      remaining -= contiguous;

      // 通知消费者有新数据
      data_available.notify_one();
    }
  }

  // 线程安全的读取方法
  size_t read(float* dest, size_t max_samples) {
    std::unique_lock<std::mutex> lock(mutex);

    // 等待数据可用
    data_available.wait(lock, [this] { return available() > 0; });

    size_t read = 0;
    while (read < max_samples && available() > 0) {
      // 计算连续可读数据
      const size_t contiguous =
          std::min(max_samples - read, contiguous_available());

      // 读取数据
      for (size_t i = 0; i < contiguous; ++i) {
        dest[read + i] = buffer[read_pos];
        read_pos = (read_pos + 1) % buffer.size();
      }

      read += contiguous;

      // 通知生产者有空间
      space_available.notify_one();
    }
    return read;
  }

  // 线程安全的清空操作（关键修改）
  void clear() {
    std::unique_lock<std::mutex> lock(mutex);
    read_pos = 0;   // 重置读指针
    write_pos = 0;  // 重置写指针
    // 通知所有等待空间的线程（生产者）
    space_available.notify_all();
    // 通知所有等待数据的线程（消费者）
    data_available.notify_all();
  }

 private:
  // 当前可用数据量
  size_t available() const {
    return (write_pos >= read_pos) ? (write_pos - read_pos)
                                   : (buffer.size() - read_pos + write_pos);
  }

  // 当前可用空间
  size_t available_space() const {
    return buffer.size() - available() - 1;  // 保留一个位置避免完全满
  }

  // 连续可读空间
  size_t contiguous_available() const {
    return (read_pos <= write_pos) ? (write_pos - read_pos)
                                   : (buffer.size() - read_pos);
  }

  // 连续可写空间
  size_t contiguous_space() const {
    return (write_pos < read_pos) ? (read_pos - write_pos - 1)
                                  : (buffer.size() - write_pos);
  }

  std::vector<float> buffer;
  size_t read_pos, write_pos;
  mutable std::mutex mutex;
  std::condition_variable data_available;   // 数据可读通知
  std::condition_variable space_available;  // 空间可用通知
};